package com.franklin.ideaplugin.api.classloader;



import cn.hutool.core.io.FileUtil;
import com.franklin.ideaplugin.api.utils.DependencyUtils;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * project类加载器（用于加载工程里包含的类）
 *
 * @author Franklin
 * @since 2023/08/26 12:11
 */
public class ProjectClassLoaderManager {

   private final Project project;

   private volatile ProjectClassLoader classLoader;

    public ProjectClassLoaderManager(Project project) {
        this.project = project;
    }

    public static ProjectClassLoaderManager getInstance(Project project){
        return ServiceManager.getService(project, ProjectClassLoaderManager.class);
    }

    public static ProjectClassLoader getClassLoader(Project project){
        return getInstance(project).getClassLoader();
    }

    /**
     * 获取类加载器
     * @return
     */
    private ProjectClassLoader getClassLoader(){
        if (Objects.nonNull(classLoader)){
            return classLoader;
        }
        synchronized (project){
            if (Objects.isNull(classLoader)){
                classLoader = initClassLoader();
            }
        }
        return classLoader;
    }

    private ProjectClassLoader initClassLoader(){
        List<VirtualFile> classPath = DependencyUtils.getProjectClassPath(this.project);

        //寻找项目中的包
        URL[] urls = classPath.stream()
                .map(virtualFile -> {
                    String path = virtualFile.getPath();
                    path = path.substring(0,path.length() - 2);
                    return FileUtil.file(path);
                })
                .filter(File::exists)
                .map(File::toPath)
                .map(Path::toUri)
                .map(uri -> {
                    try {
                        return uri.toURL();
                    } catch (MalformedURLException e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList())
                .toArray(new URL[]{});
        return new ProjectClassLoader(urls);
    }
}
